'''
Created on 22/11/2011

@author: Mateo
'''

import copy
from page import Page
class Pagination(object):
    '''
    classdocs
    '''


    def __init__(self,frame,memory):
        
        '''
        Constructor
        '''
        self.paginationTable={}
        self.sizeFrame=frame
        self.unusedPages=self.initializePages(memory)
        self.unusedPages.reverse()
        self.usedPages=[]
        self.memory=memory
      
            
    def allocate(self,pid, program, mmu,memory):
        
           
        if self.isEnoughSpaceForProgram(program): # fijarse si hay al menos un bloque que quepa
            
            #que verga devuelve ??? BASE DIR
            return self.loadPagination(program,pid,memory)
                ##falta agregar a la tablita de pid y base dirs
            print("Program loaded")
        
        elif self.isEnoughSpaceForProgramCompacting(program):
            self.lru()
            self.allocate(pid, program, mmu,memory) ####caso contrario que saque una cuenta para ver si compactando se puede almacenar
            print("Program loaded after LRU")
        
        else:
            print("No hay lugar amigacho")
            mmu.thereIsNoSpaceInMemory(pid)
        
        
        return self.loadPagination(program,pid,memory)
    
    
    
    def initializePages(self,memory):
        
        last=memory.size()/self.sizeFrame
        i=0
        pages=[]
        while i<=last:
            page= Page(i,self.sizeFrame)
            pages.append(page)
            i+=1
        
           
        
        return pages
        
    def loadPagination(self,program,pid,memory):
        
        pages=(self.unusedPages)
        
        used=[]
        count=len(program)/self.sizeFrame
        
     
        if count * self.sizeFrame < len(program):
            count+=1
        
        while count >0:
            p=pages.pop()
            used.append(p)
            count-=1
        
        print(used)    
        self.paginationTable[pid]=used
        self.loadProgramP(program,used,memory)   
        self.addUsedPages(used)
        #self.sucUnusedPages(used)
    
    def loadProgramP(self,prog,used,memory):
        
        pages=(used)
        counter = 0
        c=0
        page=pages[c]
        
        for i in prog:
            
            if counter<self.sizeFrame:
                
                memory.load(page.getNumber() * self.sizeFrame + counter, i) #cargo cada instruccion en memoria
                counter += 1 
            else:
                c+=1
                
                page=pages[c]
                counter=0
                memory.load(page.getNumber() * self.sizeFrame + counter, i) #cargo cada instruccion en memoria
                counter += 1 
                
    def read(self ,pid, instrNumber ,memory):
        
        pages=self.paginationTable[pid]
        #self.sortPages(pages, lambda page: page)
        i=instrNumber  
        count=0
        
        while i > self.sizeFrame:
            i=i-self.sizeFrame
            count+=1
        
        return memory.read(pages[count].getNumber() * self.sizeFrame + i)
    
    
           
    def sortPages(self, pagesList, condition):
        
        pagesList.sort(key = condition)      

    def unload (self,pid, memory):
        
        pages=self.paginationTable[pid]
        self.unusedPages.append(pages)
        self.clearPages(pages)
            
    def clearPages(self,pages):
        
             
        for p in pages:
            self.usedPages.remove(p)

    def addUsedPages(self,lista):
        pag=(lista)     
        for p in pag:
            self.usedPages.append(p)
        
    def allocateRegister(self, value):
        
        page = self.unusedPages[0]
        dirE= page.registerAllocation()
        self.memory.load(dirE, value)
      
        return dirE
    
    def isEnoughSpaceForProgram(self, program):
        
        count=len(program)/self.sizeFrame
        
     
        if count * self.sizeFrame < len(program):
            count+=1
            
        return len(self.unusedPages) >= count